#pragma once
#include <eosiolib/asset.hpp>
#include <eosiolib/eosio.hpp>
#include <eosiolib/transaction.hpp>
#include <eosio.token/eosio.token.hpp>
#include <eosiolib/crypto.h>
#include "tools.hpp"

namespace eosio {
    class random {
        private:
            uint64_t seed = 0;
        
        public:
            account_name _self;
            random( account_name account ) {
                _self = account;
            }
        
            uint32_t range( uint32_t max, uint64_t gameid, uint64_t userid ) {
                int64_t time = current_time();
                seed = max * gameid * (time + _self);
                checksum256 result;
                sha256((char *)&seed, sizeof( seed ), &result);
                seed = result.hash[1];
                seed <<= 32;
                seed |= result.hash[0];
                
                auto pool_eos = eosio::token( N(eosio.token) ).get_balance( _self, symbol_type(S(4, EOS)).name() );
                uint64_t amount = pool_eos.amount;
                uint64_t tmp = seed * gameid * max * amount * time;
                checksum256 res;
                sha256( (char *)&tmp, sizeof(tmp), &res );
                uint64_t total = *(uint64_t *)&res.hash[8];

                checksum256 tx;
                const char *txid = tools::getTxid().c_str();
                sha256( txid, sizeof( tx ), &tx );

                uint64_t all = 1;
                for( int i = 0; i < sizeof( tx.hash ); i++ ) {
                    all = all * tx.hash[i];
                }

                all = all + (seed + gameid + max + pool_eos.amount + time + total + tapos_block_num() + tapos_block_prefix() + userid);
                checksum256 res2;
                sha256((char *)&all, sizeof( all ), &res2);

                return (uint32_t)((res2.hash[6] * res2.hash[7] * res2.hash[8] + res2.hash[0]) % max) + 1;
            }
    };
}